import org.junit.jupiter.api.Test;

import java.time.*;
import java.time.temporal.ChronoUnit;

public class InstantDemo {

    /**
     * EPOCH：指格林尼兹时间的特定时间点 1970-01-01 00:00:00。
     * MAX：instant对象能表示的最大值。
     * MIN：instant对象能表示的最小值。
     */
    @Test
    public void test01(){
        System.out.println(Instant.EPOCH); // 输出 1970-01-01T00:00:00Z
        System.out.println(Instant.MAX); // 输出 +1000000000-12-31T23:59:59.999999999Z
        System.out.println(Instant.MIN); // 输出 -1000000000-01-01T00:00:00Z
    }
}

class InstantDemo01 {

    /**
     * from(TemporalAccessor temporal)
     * 作用：从其他时间类获取instant对象。(只有含有时区或偏移量概念的时间对象才能作为参数传递）
     */
    @Test
    public void test01(){
        ZonedDateTime zonedDateTime01 = ZonedDateTime.parse("2023-01-01T12:00:00+08:00[Asia/Shanghai]");
        Instant instant01 = Instant.from(zonedDateTime01);
        System.out.println(instant01); // 输出 2023-01-01T04:00:00Z
    }

    /**
     * now()
     * 作用：获取的是此刻UTC时区的日期和时间。
     *      不管系统是哪个时区，调用该方法的结果都一样。
     *
     * now(Clock clock)
     * 作用：通过clock对象获取instant对象。
     */
    @Test
    public void test02(){
        Instant instant01 = Instant.now();
        System.out.println(instant01); // 输出 2023-05-11T01:16:06.859Z（虽然没有时区概念，但获取的时间跟此刻UTC时区的时间一样）

        Clock systemClock01 = Clock.systemDefaultZone();
        Instant instant02 = Instant.now(systemClock01);
        System.out.println(instant02); // 输出 2023-05-11T01:16:06.882Z
    }

    /**
     * ofEpochMilli(long epochMilli)
     * ofEpochSecond(long epochSecond)
     * ofEpochSecond(long epochSecond, long nanoAdjustment)
     * 作用：给定距离EPOCH的 秒数/毫秒数/纳秒数 创建instant对象。
     */
    @Test
    public void test03() {
        System.out.println(Instant.ofEpochMilli(0)); // 输出 1970-01-01T00:00:00Z
        System.out.println(Instant.ofEpochMilli(1)); // 输出 1970-01-01T00:00:00.001Z

        System.out.println(Instant.ofEpochSecond(0)); // 输出 1970-01-01T00:00:00Z
        System.out.println(Instant.ofEpochSecond(1)); // 输出 1970-01-01T00:00:01Z

        System.out.println(Instant.ofEpochSecond(0, 0)); // 输出 1970-01-01T00:00:00Z
        System.out.println(Instant.ofEpochSecond(1, 1)); // 输出 1970-01-01T00:00:01.000000001Z
    }

    /**
     * parse(CharSequence text)
     * 作用：将字符串解析成instant对象，字符串默认格式yyyy-MM-ddTHH:ss:mm.SSSZ。
     */
    @Test
    public void test04(){
        Instant instant01 = Instant.parse("2023-01-01T12:30:45.001Z");
        System.out.println(instant01); // 输出 2023-01-01T12:30:45.001Z
    }
}

class InstantDemo02{
    /**
     * atOffset(ZoneOffset offset)
     * atZone(ZoneId zone)
     * 作用：添加偏移量或时区的概念生成OffsetDateTime或ZonedDateTime对象。
     */
    @Test
    public void test01(){
        Instant instant01 = Instant.parse("2023-01-01T10:00:00Z");
        ZoneOffset zoneOffset = ZoneOffset.of("+08:00");
        ZoneId zoneRegion = ZoneId.of("Asia/Shanghai");
        OffsetDateTime offsetDateTime01 = instant01.atOffset(zoneOffset);
        ZonedDateTime zonedDateTime01 = instant01.atZone(zoneRegion);

        System.out.println(offsetDateTime01); // 输出 2023-01-01T18:00+08:00
        System.out.println(zonedDateTime01); // 输出 2023-01-01T18:00+08:00[Asia/Shanghai]
    }

    /**
     * toEpochMilli()
     * 作用：将instant对象转换成距离EPOCH的毫秒数。
     */
    @Test
    public void test02(){
        Instant instant01 = Instant.parse("1970-01-01T00:00:00.000Z");
        Instant instant02 = Instant.parse("1970-01-01T00:00:01.000Z");
        System.out.println(instant01.toEpochMilli()); // 输出 0
        System.out.println(instant02.toEpochMilli()); // 输出 1000
    }

    /**
     * truncatedTo(TemporalUnit unit)
     * 作用：根据时间单位截取instant对象。
     */
    @Test
    public void test03(){
        Instant instant01 = Instant.parse("2023-01-01T12:30:45.001Z");
        System.out.println(instant01); // 输出 2023-01-01T12:30:45.001Z
        System.out.println(instant01.truncatedTo(ChronoUnit.SECONDS)); // 输出 2023-01-01T12:30:45Z
        System.out.println(instant01.truncatedTo(ChronoUnit.MINUTES)); // 输出 2023-01-01T12:30:00Z
        System.out.println(instant01.truncatedTo(ChronoUnit.HOURS)); // 输出 2023-01-01T12:00:00Z
    }

    /**
     * until(Temporal endExclusive, TemporalUnit unit)
     * 作用：根据时间单位计算两个instant对象的差值。
     */
    @Test
    public void test04(){
        Instant instant01 = Instant.parse("2023-01-01T01:00:00.000Z");
        Instant instant02 = Instant.parse("2023-01-01T02:00:00.000Z");
        System.out.println(instant01.until(instant02, ChronoUnit.HOURS)); // 输出 1
        System.out.println(instant01.until(instant02, ChronoUnit.MINUTES)); // 输出 60
        System.out.println(instant01.until(instant02, ChronoUnit.SECONDS)); // 输出 3600
    }
}